﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Nirvana
{
    public sealed class TextureCache
    {
        private static Logger logger = LogSystem.GetLogger("TextureCache");
        private Texture _texture;
        private float defaultReleaseAfterFree = 30f;
        private float lastFreeTime = -1f;
        private Dictionary<Texture, TextureCache> textureCacheMap;
        public AssetID AssetID { get; private set; }
        public int ReferenceCount { get; private set; }
        public float LastFreeTime
        {
            get { return lastFreeTime; }
        }
        public float ReleaseAfterFree { get; private set; }
        public bool IsSync { get; set; }
        public string Error { get; private set; }
        /// <summary>
        /// 是否以文本字节流保存的纹理
        /// </summary>
        public bool IsTextAsset { get; private set; }
		private bool isLoaded;
        public bool Loading { get; set; }
        public TextureCache(AssetID asset, Dictionary<Texture, TextureCache> map)
        {
            this.AssetID = asset;
            this.textureCacheMap = map;
        }

        public void SetReleaseTimeAfterFree(float t)
        {
            this.defaultReleaseAfterFree = t;
            this.ReleaseAfterFree = t;
        }

        public void Retain()
        {
            ReferenceCount++;
        }

        public void Release()
        {
            ReferenceCount--;
            lastFreeTime = Time.time;
            if (ReferenceCount < 0)
            {
                Debug.LogErrorFormat("[TextureCahce] referenceCount is error {0} {1}",
                    this.AssetID.ToString(), this.ReferenceCount);
            }
        }

        public void Load(AssetID assetID)
        {
           this.Loading = true;
            this.AssetID = assetID;
            Scheduler.RunCoroutine(WaitLoad(assetID));
        }

        public bool IsNotNull()
        {
            return this._texture != null;
        }

        public Texture GetObject()
        {
            return this._texture;
        }



        private IEnumerator WaitLoad(AssetID assetID)
        {
            WaitLoadObject waitLoadObject = null;
            if (this.IsSync)
            {
                waitLoadObject = AssetManager.LoadObjectSync(assetID, typeof(Object));
            }
            else
            {
                waitLoadObject = AssetManager.LoadObject(assetID, typeof(Object));
            }
            yield return waitLoadObject;

            if (!string.IsNullOrEmpty(waitLoadObject.Error))
            {
                this.Error = waitLoadObject.Error;
                yield break;
            }

            var obj = waitLoadObject.GetObject();
            this._texture = (obj as Texture);
            if (this._texture == null)
            {
                TextAsset textAsset = obj as TextAsset;
                if (textAsset != null)
                {
                    this._texture = this.LoadTextAsset(textAsset);
                    Resources.UnloadAsset(textAsset);
                    this.IsTextAsset = true;
                }
            }
            if (this._texture == null)
            {
                this.Error = string.Format("The asset {0} is not a Texture.", assetID);
                yield break;
            }

            ReleaseAfterFree = defaultReleaseAfterFree;
 			isLoaded = true;
            if (textureCacheMap.ContainsKey(this._texture))
            {
                logger.LogWarning("The Texture {0} has been loaded.", assetID);
                this.textureCacheMap[this._texture] = this;
            }
            else
            {
                this.textureCacheMap.Add(this._texture, this);
            }

            yield break;

        }

        private Texture2D LoadTextAsset(TextAsset asset)
        {
            byte[] bytes = asset.bytes;
            TextureFormat textureFormat = TextureFormat.RGB24;
            if (bytes != null && bytes[1] == 80 && bytes[2] == 78 && bytes[3] == 71)
            {
                textureFormat = TextureFormat.RGBA32;
            }
            Texture2D texture2D = new Texture2D(2, 2, textureFormat, false);
            if (!ImageConversion.LoadImage(texture2D, bytes, true))
            {
                return null;
            }
            texture2D.wrapMode = TextureWrapMode.Clamp;
            return texture2D;
        }


    }
}


